package scales.xml.serializers
import scales.xml._
import dsl.DslBuilder
import scales.utils._
case class StreamStatus(output : XmlOutput, thrown: Option[Throwable] = None, isEmpty : Boolean = false)
object StreamSerializer {
import ScalesXml._
val dummy = Left(Elem("dummy"l))
val dummyIterable : Iterable[PullType] = List(dummy)
def pump(event: (PullType, PullType), status : StreamStatus, serializer: Serializer) : StreamStatus = {
import status.output.{serializerF => defaultSerializerFactory}
import status.{output, isEmpty}
if (status.thrown.isDefined) status
else {
val (ev, next) = event
ev match {
case Left(i: XmlItem) =>
StreamStatus(output, serializer.item(i, output.path), false)
case Left(x: Elem) =>
if (next.isRight) {
val nc = doElement(x, output.currentMappings.top)
StreamStatus(output, serializer.emptyElement(x.name, x.attributes, nc.declMap, nc.addDefault, x.name :: output.path), true)
} else {
val npath = x.name :: output.path
val nc = doElement(x, output.currentMappings.top)
StreamStatus(output.copy(currentMappings = output.currentMappings.push(nc.mappings), path = npath),
serializer.startElement(x.name, x.attributes, nc.declMap, nc.addDefault, npath), false)
}
case Right(endElem) =>
if (isEmpty)
StreamStatus(output, None, false)
else
StreamStatus(output.copy(currentMappings = output.currentMappings.pop,
path = output.path.tail),
serializer.endElement(endElem.name, output.path), false)
}
}
}
}
class StreamSerializer[T](toP : T => Iterator[PullType]) extends SerializeableXml[T] {
import StreamSerializer._
def doc(it: T) : DocLike = EmptyDoc()
def apply(itT: T)(out: XmlOutput, serializer: Serializer): (XmlOutput, Option[Throwable]) = {
import out.serializerF
val it = toP(itT)
val r = it.++(dummyIterable.iterator).sliding(2).foldLeft(StreamStatus(out)) { (status, two) =>
if (status.thrown.isDefined) status
else {
val asList = two.toList
if (!((asList.size == 1) && (asList.head eq dummy))) {
val List(ev, next) = asList
pump((ev, next), status, serializer)
} else StreamStatus(status.output, Some(NoDataInStream()), true)
}
}
(r.output, r.thrown)
}
}
trait SerializerImplicits {
implicit val treeSerializeable: SerializeableXml[XmlTree] = new SerializeableXml[XmlTree] {
def doc(it: XmlTree) = Doc(it)
def apply(it: XmlTree)(out: XmlOutput, serializer: Serializer): (XmlOutput, Option[Throwable]) = {
import out.serializerF
fold[XmlItem, Elem, XCC, (XmlOutput, Option[Throwable])]((out, None)) { (iorsw, pair) =>
val (output, y) = pair
if (y.isDefined) pair
else
iorsw match {
case Left(item) => (output, serializer.item(item, output.path))
case Right(walk) =>
val x = walk.section
if (!walk.hasChildren) {
val nc = doElement(x, output.currentMappings.top)
(output, serializer.emptyElement(x.name, x.attributes, nc.declMap, nc.addDefault, x.name :: output.path))
} else {
if (walk.isStart) {
val npath = x.name :: output.path
val nc = doElement(x, output.currentMappings.top)
(output.copy(currentMappings = output.currentMappings.push(nc.mappings),
path = npath),
serializer.startElement(x.name, x.attributes, nc.declMap, nc.addDefault, npath))
} else {
(output.copy(currentMappings = output.currentMappings.pop,
path = output.path.tail), serializer.endElement(x.name, output.path))
}
}
}
}(it)
} }
implicit val builderSerializeable : SerializeableXml[DslBuilder] = new SerializeableXml[DslBuilder] {
def doc(it: DslBuilder) = Doc(it.toTree)
def apply(it: DslBuilder)(out: XmlOutput, serializer: Serializer): (XmlOutput, Option[Throwable]) = treeSerializeable(it.toTree)(out, serializer)
}
implicit val docSerializeable : SerializeableXml[Doc]= new SerializeableXml[Doc] {
def doc(it: Doc) = it
def apply(it: Doc)(out: XmlOutput, serializer: Serializer): (XmlOutput, Option[Throwable]) = treeSerializeable(it.rootElem)(out, serializer)
}
implicit val elemSerializable : SerializeableXml[Elem] = new SerializeableXml[Elem] {
def doc(it: Elem) = Doc(DslBuilder.elem2tree(it))
def apply(it: Elem)(out: XmlOutput, serializer: Serializer): (XmlOutput, Option[Throwable]) = treeSerializeable(DslBuilder.elem2tree(it))(out, serializer)
}
implicit val streamSerializeable: SerializeableXml[Iterator[PullType]] = new StreamSerializer(identity)
implicit val pullCloseableOnlySerializeable: SerializeableXml[CloseablePull] = new StreamSerializer[CloseablePull](identity){
override def doc(it: CloseablePull) = it
}
implicit val pullOnlySerializeable: SerializeableXml[XmlPull] = new StreamSerializer[XmlPull](identity) {
override def doc(it: XmlPull) = it
}
implicit val pullAndDocSerializeable: SerializeableXml[(Iterator[PullType], DocLike)] = new StreamSerializer[(Iterator[PullType], DocLike)](_._1) {
override def doc(it: (Iterator[PullType], DocLike)) = it._2
}
}